#include <tipos.h>
#include <syscalls.h>
#include <fs.h>
#include <string.h>
#include <stdio.h>
#include <i386.h>

#define CANT_BUFFER 4

#define BUFFER_LEN 4096

#define DEBUG_KY(x) 

struct	_buf_info {
	int size;
	char * ptr;
};
typedef struct _buf_info buf_info;

FILE_DESC buffers_free[2];
FILE_DESC buffers_to_encrypt[2];
FILE_DESC buffers_to_write[2];


void encrypt(char *buffer, int size) {
	
	int i;
	
	for (i = 0; i < size; i++) {
		buffer[i] = toUpper(buffer[i]);
	}
}

void encrypt2(char *buffer, int size) {
	
	char key[] = "pepe";
	int key_len, i;
	
	key_len = strlen(key);
	
	for (i = 0; i < size; i++) {
		buffer[i] ^= key[i % key_len];
	}
}

void
reader()
{
	int leidos;
	buf_info buffer_info; 
	
	stdio_printf("krypto reader (%d)\n", getpid() );
			
	DEBUG_KY(breakpoint();)
	
	flush(buffers_free[1]);
	flush(buffers_to_encrypt[0]);
	flush(buffers_to_write[0]);
	flush(buffers_to_write[1]);
	
	FILE_DESC file;
	file = open("/disk/kernel.bin", FS_OPEN_RDWR);
	
	while (1) {
		
		leidos = read(buffers_free[0], &buffer_info, sizeof(buffer_info));
		stdio_printf("R %d %x %d\n", leidos, buffer_info.ptr, buffer_info.size);
		DEBUG_KY(breakpoint();)
		
		leidos = read(file, buffer_info.ptr, BUFFER_LEN);
		stdio_printf("RF %d\n", leidos);
		DEBUG_KY(breakpoint();)
		
		if (leidos == 0)
			break;
		
		buffer_info.size = leidos;
		
		write(buffers_to_encrypt[1], &buffer_info, sizeof(buffer_info));
	}
	
	flush(buffers_to_encrypt[1]);
	flush(buffers_free[0]);
	stdio_printf("krypto reader done\n");
}

void
encrypter()
{
	int leidos;
	buf_info buffer_info; 
	
	stdio_printf("krypto encrypt (%d)\n", getpid() );
	
	DEBUG_KY(breakpoint();)
	
	flush(buffers_free[0]);
	flush(buffers_free[1]);
	flush(buffers_to_encrypt[1]);
	flush(buffers_to_write[0]);
	
	while (1) {
		
		leidos = read(buffers_to_encrypt[0], &buffer_info, sizeof(buffer_info));
		stdio_printf("E %d %x %d\n", leidos, buffer_info.ptr, buffer_info.size);
		DEBUG_KY(breakpoint();)
	
		if (leidos == 0)
			break;
		
		encrypt(buffer_info.ptr, buffer_info.size);
		
		write(buffers_to_write[1], &buffer_info, sizeof(buffer_info));
		
	}
	
	flush(buffers_to_write[1]);
	flush(buffers_to_encrypt[0]);
	
	stdio_printf("krypto encrypt done\n");
}

void
writer()
{
	int leidos;
	buf_info buffer_info; 
	
	stdio_printf("krypto write (%d)\n", getpid() );
	
	DEBUG_KY(breakpoint();)
	
	flush(buffers_free[0]);
	flush(buffers_to_encrypt[1]);
	flush(buffers_to_encrypt[0]);
	flush(buffers_to_write[1]);
	
	FILE_DESC file;
	file = open("/serial0", FS_OPEN_RDWR);
	
	while (1) {
					
		leidos = read(buffers_to_write[0], &buffer_info, sizeof(buffer_info));
		stdio_printf("W %d %x %d\n", leidos, buffer_info.ptr, buffer_info.size);
		DEBUG_KY(breakpoint();)
		
		if (leidos == 0)
			break;
		
		write(file, buffer_info.ptr, buffer_info.size);
		
		buffer_info.size = BUFFER_LEN;
		write(buffers_free[1], &buffer_info, sizeof(buffer_info));
		
	}
	
	flush(buffers_free[1]);
	flush(buffers_to_write[0]);
	stdio_printf("krypto write done\n");
}

void
buffer_new()
{
	buf_info buffer_info; 
	buffer_info.ptr = palloc();
	*(buffer_info.ptr) = 'B';
	
	stdio_printf("Pagina: %x\n", buffer_info.ptr);
	
	DEBUG_KY(breakpoint();)
	
	share_page(buffer_info.ptr);
	
	DEBUG_KY(breakpoint();)
	
	buffer_info.size = BUFFER_LEN;
	
	write(buffers_free[1], &buffer_info, sizeof(buffer_info));
}

int main(void) {
 
	int i;

	
	stdio_init();

	//Pido los pipes
	pipe(buffers_free);
	pipe(buffers_to_encrypt);
	pipe(buffers_to_write);
	
	for (i = 0; i < CANT_BUFFER; i++) {
		buffer_new();
	}
	
	stdio_print("krypto 2.0\n");
	
	if( fork() )
	{
		if( fork() )
		{
			reader();
		}
		else
		{
			encrypter();
		}
	}
	else
	{
		writer();
		
		stdio_print("Listo! - Presione una tecla para finalizar\n");
		stdio_wait();
	}
	
	stdio_close();

	return 0;
}

